package com.amap.apis.cluster;

import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;

import com.amap.api.maps.AMap;
import com.amap.api.maps.CameraUpdateFactory;
import com.amap.api.maps.MapView;
import com.amap.api.maps.model.LatLng;
import com.amap.api.maps.model.LatLngBounds;
import com.amap.api.maps.model.Marker;
import com.amap.apis.cluster.demo.RegionItem;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class MainActivity extends Activity{

    private MapView mMapView;//地图View
    private AMap mAMap;//地图
    private int clusterRadius = 100;//聚合的半径
    private Map<Integer, Drawable> mBackDrawAbles = new HashMap<Integer, Drawable>();//存放聚合的图片的集合
    private ClusterOverlay mClusterOverlay;//聚合的帮助类

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        initView(savedInstanceState);

        initMap();
    }

    /**
     * 初始化地图View
     * @param savedInstanceState
     */
    private void initView(Bundle savedInstanceState) {
        mMapView = (MapView) findViewById(R.id.map);
        mMapView.onCreate(savedInstanceState);
    }

    /**
     * 初始化AMap
     */
    private void initMap() {
        if (mAMap == null) {
            // 初始化地图
            mAMap = mMapView.getMap();
            //加载更多的监听
            mAMap.setOnMapLoadedListener(mOnMapLoadedListener);
            //点击可以动态添加点
            mAMap.setOnMapClickListener(mOnMapClickListener);
        }
    }

    /**
     * 地图加载完执行的方法
     */
    AMap.OnMapLoadedListener mOnMapLoadedListener = new AMap.OnMapLoadedListener() {
        @Override
        public void onMapLoaded() {
            //1、开启线程，添加测试数据
            new Thread() {
                @Override
                public void run() {
                    List<ClusterItem> items = new ArrayList<>();
                    //随机10000个点
                    for (int i = 0; i < 10000; i++) {
                        double lat = Math.random() + 39.474923;
                        double lon = Math.random() + 116.027116;
                        LatLng latLng = new LatLng(lat, lon, false);
                        RegionItem regionItem = new RegionItem(latLng, "test" + i);
                        items.add(regionItem);
                    }

                    //2、内部有两个线程，一个线程是用来计算聚合点的集合，一个线程是用来绘制Marker点
                    mClusterOverlay = new ClusterOverlay(mAMap, items,
                            dp2px(getApplicationContext(), clusterRadius),
                            getApplicationContext());

                    //3、设置聚合点显示的样式 + 点击聚合点执行的方法
                    mClusterOverlay.setClusterRenderer(mClusterRender);
                    mClusterOverlay.setOnClusterClickListener(mClusterClickListener);

                }
            }.start();
        }

        /**
         * 聚合点加载的时候之心的方法
         */
        ClusterRender mClusterRender = new ClusterRender() {
            @Override
            public Drawable getDrawAble(int clusterNum) {
                int radius = dp2px(getApplicationContext(), 80);//获得 80dp对应的px大小
                if (clusterNum == 1) {//聚合的个数为1个的时候
                    Drawable bitmapDrawable = mBackDrawAbles.get(1);
                    if (bitmapDrawable == null) {
                        bitmapDrawable =
                                getApplication().getResources().getDrawable(
                                        R.drawable.icon_openmap_mark);
                        mBackDrawAbles.put(1, bitmapDrawable);
                    }

                    return bitmapDrawable;
                } else if (clusterNum < 5) {//聚合的个数<5个的时候

                    Drawable bitmapDrawable = mBackDrawAbles.get(2);
                    if (bitmapDrawable == null) {
                        bitmapDrawable = new BitmapDrawable(null, drawCircle(radius,
                                Color.argb(159, 210, 154, 6)));
                        mBackDrawAbles.put(2, bitmapDrawable);
                    }

                    return bitmapDrawable;
                } else if (clusterNum < 10) {//聚合的个数<10个的时候
                    Drawable bitmapDrawable = mBackDrawAbles.get(3);
                    if (bitmapDrawable == null) {
                        bitmapDrawable = new BitmapDrawable(null, drawCircle(radius,
                                Color.argb(199, 217, 114, 0)));
                        mBackDrawAbles.put(3, bitmapDrawable);
                    }

                    return bitmapDrawable;
                } else {//聚合的个数 >=10 个的时候，返回对应的Drawable
                    //逻辑
                    //主要是为了性能
                    //1、首先从Map中取出聚合的图片
                    //2、如果图片为空，那么就重新构造一个
                    //如果不为空，那么就使用这个图片
                    Drawable bitmapDrawable = mBackDrawAbles.get(4);
                    if (bitmapDrawable == null) {
                        bitmapDrawable = new BitmapDrawable(null, drawCircle(radius,
                                Color.argb(235, 215, 66, 2)));
                        mBackDrawAbles.put(4, bitmapDrawable);
                    }
                    return bitmapDrawable;
                }
            }

            /**
             * 获得一个圆形的Bitmap
             * @param radius
             * @param color
             * @return
             */
            private Bitmap drawCircle(int radius, int color) {
                //1、构造Bitmap,同时构造Canvas(bitmap作为背景)
                Bitmap bitmap = Bitmap.createBitmap(radius * 2, radius * 2, Bitmap.Config.ARGB_8888);
                Canvas canvas = new Canvas(bitmap);

                //2、构造矩形
                RectF rectF = new RectF(0, 0, radius * 2, radius * 2);

                //3、构造画笔
                Paint paint = new Paint();
                paint.setColor(color);

                //4、绘制圆
                canvas.drawArc(rectF, 0, 360, true, paint);//绘制圆
                return bitmap;
            }
        };

        /**
         * 聚合点被点击的时候执行的方法
         */
        ClusterClickListener mClusterClickListener = new ClusterClickListener() {

            /**
             * @param marker 对应的点
             * @param clusterItems 聚合点对应的内部的点
             */
            @Override
            public void onClick(Marker marker, List<ClusterItem> clusterItems) {
                //1、代表了经纬度代表的一个矩形区域
                LatLngBounds.Builder builder = new LatLngBounds.Builder();

                //2、根据中心点，进行小范围的一个延伸，的到一个新坐标的builder对象
                for (ClusterItem clusterItem : clusterItems) {
                    builder.include(clusterItem.getPosition());
                }

                //3、创建矩形区域
                LatLngBounds latLngBounds = builder.build();

                //4、生成一个经纬度的限制区域。第二个参数表示padding。
                mAMap.animateCamera(CameraUpdateFactory.newLatLngBounds(latLngBounds, 0));
            }
        };
    };

    /**
     * Map被点击执行的方法
     */
    AMap.OnMapClickListener mOnMapClickListener =  new AMap.OnMapClickListener() {
        @Override
        public void onMapClick(LatLng latLng) {
            double lat = Math.random() + 39.474923;
            double lon = Math.random() + 116.027116;

            LatLng latLng1 = new LatLng(lat, lon, false);
            RegionItem regionItem = new RegionItem(latLng1, "test");
            mClusterOverlay.addClusterItem(regionItem);

        }
    };

    protected void onResume() {
        super.onResume();
        mMapView.onResume();
    }

    protected void onPause() {
        super.onPause();
        mMapView.onPause();
    }

    protected void onDestroy() {
        super.onDestroy();
        //销毁资源
        mClusterOverlay.onDestroy();
        mMapView.onDestroy();
    }

    /**
     * 根据手机的分辨率从 dp 的单位 转成为 px(像素)
     */
    public int dp2px(Context context, float dpValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f);
    }

}
